package org.login.handler;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.common.dispatcher.ProtoDispatcher;
import org.common.netty.BaseNettyHandler;
import org.common.netty.Pack;
import org.common.netty.PackCodec;
import org.common.utils.SpringUtils;
import org.login.GameServerManger;
import org.login.LoginConfig;
import org.login.obj.GameServerContext;
import org.protobuf.InnerServerMsg;
import org.protobuf.ProtoEnumMsg;

import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.util.HashMap;

/**
 * 游戏服netty事件处理
 */
@Slf4j
@ChannelHandler.Sharable
public class LoginToGameNettyHandler extends BaseNettyHandler {


    // 登录服ctx自定义属性
    private static final AttributeKey<HashMap<String, Object>> gameServerSocketAttr = AttributeKey.valueOf("GameServerSocketAttr");


    /**
     * 收到协议数据
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, byte[] msg) throws Exception {
        HashMap<String, Object> attr = ctx.channel().attr(gameServerSocketAttr).get();
        if (attr == null) {
            attr = new HashMap<>();
            ctx.channel().attr(gameServerSocketAttr).set(attr);
        }
        Pack decode = PackCodec.decode(msg);
        int cmdId = decode.getCmdId();
        GameServerManger gameServerManger = SpringUtils.getBean(GameServerManger.class);
        // 游戏服注册
        if (cmdId == ProtoEnumMsg.CMD.ID.GAME_SERVER_REGISTER_VALUE) {
            InnerServerMsg.G2LRegister g2LRegister = InnerServerMsg.G2LRegister.parseFrom(decode.getData());
            int serverId = g2LRegister.getServerId();
            log.info("游戏服注册，serverId={}", serverId);
            gameServerManger.registerGameServer(serverId, ctx.channel());
            LoginConfig loginConfig = SpringUtils.getBean(LoginConfig.class);
            InnerServerMsg.L2GRegister.Builder builder = InnerServerMsg.L2GRegister.newBuilder();
            builder.setSuccess(true);
            builder.setServerId(loginConfig.getServerId());
            Pack pack = new Pack(cmdId, builder);
            ctx.writeAndFlush(PackCodec.encode(pack));
            attr.put("serverId", serverId);
            return;
        }
        int serverId = (int) attr.get("serverId");
        GameServerContext gameServer = gameServerManger.getGameServer(serverId);
        if (gameServer == null) {
            log.error("GameServer is null. serverId = {}", serverId);
            return;
        }
        ProtoDispatcher dispatcher = SpringUtils.getBean(ProtoDispatcher.class);
        dispatcher.dispatch(decode, gameServer);
    }


    /**
     * 建立连接
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = address.getAddress().getHostAddress();

        if (ctx.channel().isActive()) {
            log.info("内部服务创建连接—成功:ip = {}", ip);
        }
    }


    /**
     * 连接断开
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("连接断开");
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if (cause instanceof ClosedChannelException) {
            return;
        }
        cause.printStackTrace();
        ctx.close();
    }
}
